package compute

import (
	"fmt"
	"strconv"
	"sync"
	"time"
)

func SyncFunc() {

	// demo 互斥锁sync.mutex
	var lock sync.Mutex
	go func() {
		lock.Lock()         //加锁
		defer lock.Unlock() //释放锁
		// fmt.Print(time.Second / 10)
		fmt.Print("1,加锁 \n")
	}()

	//time.second 是1s，互斥锁需要等待上一个释放以后才能继续执行
	// time.Sleep(time.Second / 10)

	go func() {
		lock.Lock()         //加锁
		defer lock.Unlock() //释放锁
		fmt.Print("2,释放锁")
	}()

	time.Sleep(time.Second * 4)

}

func SyncRw_Func() {
	var rwLock sync.RWMutex
	//获取读锁
	for i := 0; i < 5; i++ {
		go func(i int) {
			rwLock.RLock()
			defer rwLock.RLocker()
			fmt.Println("read func " + strconv.Itoa(i) + "get rlock at " + time.Now().String())
			time.Sleep(time.Second)
		}(i)
	}

	//获取写锁
	for i := 0; i < 5; i++ {
		go func(i int) {
			rwLock.Lock()
			defer rwLock.Unlock()
			fmt.Println("write func " + strconv.Itoa(i) + "get wlock at" + time.Now().String())

		}(i)
	}

	time.Sleep(time.Second * 3)

}

func Sync_WaitGroup() {
	var waitGroup sync.WaitGroup
	//添加等待goroutine 数量为5
	waitGroup.Add(5)

	for i := 0; i < 5; i++ {
		go func(i int) {
			fmt.Println("work " + strconv.Itoa(i) + " is done at " + time.Now().String())

			//等待1 s后减少等待数 1
			// time.Sleep(time.Second)
			waitGroup.Done()
		}(i)
	}
	waitGroup.Wait()
	fmt.Println("all works are done at " + time.Now().String())

}

var syncMap sync.Map
var waitGroup sync.WaitGroup

func Sync_Map() {

	routinseSize := 5
	//让主线程等待数据添加完毕
	waitGroup.Add(routinseSize)
	//并发添加数据
	for i := 0; i < routinseSize; i++ {
		go addNumber(i * 10)
	}

	//开始等待
	waitGroup.Wait()
	var size int
	//统计数量
	syncMap.Range(func(key, value interface{}) bool {
		size++
		return true

	})
	fmt.Println("syncMap current size is " + strconv.Itoa(size))
	//获取键为 0 的值
	value, ok := syncMap.Load(0)
	if ok {
		fmt.Println("key 0 has value", value, "")
	}

}

func addNumber(begin int) {
	//往syncMap中加入数据
	for i := 0; i < begin+3; i++ {
		syncMap.Store(i, i)
	}
	//通知数据已添加完毕
	waitGroup.Done()
}
